#import "Vector3.h"

#include <math.h>

static Vector3 _vecZero =	{ 0.0f,0.0f,0.0f};
static Vector3 _vecOne =	{ 1.0f,1.0f,1.0f};

static Vector3 _vecUnitX =	{ 1.0f,0.0f,0.0f};
static Vector3 _vecUnitY =	{ 0.0f,1.0f,0.0f};
static Vector3 _vecUnitZ =	{ 0.0f,0.0f,1.0f};

static Vector3 _vecUnitNegX =	{ -1.0f,0.0f,0.0f};
static Vector3 _vecUnitNegY =	{ 0.0f,-1.0f,0.0f};
static Vector3 _vecUnitNegZ =	{ 0.0f,0.0f,-1.0f};

const Vector3 *vecZero = &_vecZero;
const Vector3 *vecOne = &_vecOne;

const Vector3 *vecUnitX = &_vecUnitX;
const Vector3 *vecUnitY = &_vecUnitY;
const Vector3 *vecUnitZ = &_vecUnitZ;

const Vector3 *vecUnitNegX = &_vecUnitNegX;
const Vector3 *vecUnitNegY = &_vecUnitNegY;
const Vector3 *vecUnitNegZ = &_vecUnitNegZ;

// Vector Ctor

Vector3	Vector3Make		(float x,float y,float z)
{
	Vector3 v = {x,y,z};
	
	return v;
}

void	vec3Ctor1		(Vector3 *ctorV,float x,float y,float z)
{
	ctorV->x = x; ctorV->y = y; ctorV->z = z;
}

void	vec3Ctor2		(Vector3 *ctorV,const float *xyz)
{
	ctorV->x = xyz[0]; ctorV->y = xyz[1]; ctorV->z = xyz[2];
}

void	vec3Ctor3		(Vector3 *ctorV,const Vector3 *v)
{
	ctorV->x = v->x; ctorV->y = v->y; ctorV->z = v->z;
}

// Vector Constants

inline void vec3Zero(Vector3 *v)
{
	v->x = v->y = v->z = 0.0f;
}

inline void vec3One(Vector3 *v)
{
	v->x = v->y = v->z = 1.0f;
}

inline void vec3UnitX(Vector3 *v)
{
	*v = _vecUnitX;
}

inline void vec3UnitY(Vector3 *v)
{
	*v = _vecUnitY;
}

inline void vec3UnitZ(Vector3 *v)
{
	*v = _vecUnitZ;
}

// Vector Accessor

float vec3Component(const Vector3 *v,char index)
{
	return *(((float*)v) + index);
}


// Vector - Float 

void vec3AddFloat(const Vector3 *v,float value,Vector3 *result)
{
	result->x = v->x + value;
	result->y = v->y + value;
	result->z = v->z + value;
}

void vec3SubFloat(const Vector3 *v,float value,Vector3 *result)
{
	result->x =  v->x - value;
	result->y =  v->y - value;
	result->z =  v->z - value;
}

void vec3MulFloat(const Vector3 *v,float value,Vector3 *result)
{
	result->x =  v->x * value;
	result->y =  v->y * value;
	result->z =  v->z * value;
}

void vec3DivFloat(const Vector3 *v,float value,Vector3 *result)
{
	result->x =  v->x / value;
	result->y =  v->y / value;
	result->z =  v->z / value;
}

// Vector - Vector

void vec3Add(const Vector3 *v1,const Vector3 *v2,Vector3 *result)
{
	result->x = v1->x + v2->x;
	result->y = v1->y + v2->y;
	result->z = v1->z + v2->z;
}

void vec3Sub(const Vector3 *v1,const Vector3 *v2,Vector3 *result)
{
	result->x = v1->x - v2->x;
	result->y = v1->y - v2->y;
	result->z = v1->z - v2->z;
}

float vec3Dot(const Vector3 *v1,const Vector3 *v2)
{
	return v1->x*v2->x + v1->y*v2->y + v1->z*v2->z;
}

void vec3Cross(const Vector3 *v1,const Vector3 *v2,Vector3 *res)
{
	// Ref: http://en.wikipedia.org/wiki/Cross_product
	// dot(a,b) = (a2b3 − a3b2, a3b1 − a1b3, a1b2 − a2b1).
	
	Vector3 result;
	
	result.x = v1->y*v2->z - v1->z*v2->y;
	result.y = v1->z*v2->x - v1->x*v2->z;
	result.z = v1->x*v2->y - v1->y*v2->x;
	
	*res = result;
}

void vec3Norm1(Vector3 *v)
{
//	float k = 1.0f/vel3Len(v);
//	return vec3MulFloat(v,k); 
	
	vec3DivFloat(v,vec3Len(v),v); 
}

void vec3Norm2(const Vector3 *v,Vector3 *result)
{
	//	float k = 1.0f/vel3Len(v);
	//	return vec3MulFloat(v,k); 
	
	vec3DivFloat(v,vec3Len(v),result); 
}

float vec3Len(const Vector3 *v)
{
	return sqrtf(v->x*v->x + v->y*v->y + v->z*v->z);
}

float vec3LenSqr(const Vector3 *v)
{
	return v->x*v->x + v->y*v->y + v->z*v->z;
}

void vec3Neg1(Vector3 *v)
{
	v->x = -v->x;
	v->x = -v->y;
	v->x = -v->z;
}

void vec3Neg2(const Vector3 *v,Vector3 *result)
{
	result->x = -v->x;
	result->x = -v->y;
	result->x = -v->z;
}